//
//  ViewController.m
//  DynamicAnimator
//
//  Created by ZJ on 2018/8/11.
//  Copyright © 2018年 iCatch Technology Inc. All rights reserved.
//

#import "ViewController.h"

@interface ZJView : UIView

@property (nonatomic, assign) CGRect redRect;
@property (nonatomic, assign) CGPoint stat;
@property (nonatomic, assign) CGPoint end;

@end

@implementation ZJView

- (void)drawRect:(CGRect)rect {
//    UIBezierPath *path = [UIBezierPath bezierPath];
//
//    [path moveToPoint:CGPointMake(0, 200)];
//    [path addLineToPoint:CGPointMake(200, 250)];
//
//    [path stroke];
    
//    [[UIBezierPath bezierPathWithRect:self.redRect] stroke];
    
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    [path moveToPoint:self.stat];
    [path addLineToPoint:self.end];
    
    [path stroke];
}

@end

@interface ViewController () <UICollisionBehaviorDelegate>

@property (nonatomic, weak) UIView *redView;
@property (nonatomic, weak) UIView *blueView;

@property (nonatomic, strong) UIDynamicAnimator *animator; // 必须设置成全局属性才有作用
@property (nonatomic, strong) UIAttachmentBehavior *attach;


@end

@implementation ViewController

- (void)loadView {
    self.view = [[ZJView alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.view.backgroundColor = [UIColor whiteColor];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
//    [self collisionBehavior];
    
//    [self snapBehavior];
//    [self attachmentBehavior];
//    [self attachmentBehaviorTest];[
//    [self attachmentBehaviorTest2];
//    [self pushBehaviorTest];
    [self dynamicItemBehaviorTest];
}

#pragma mark - 动力学元素自身(UIDynamicItemBehavior)
- (void)dynamicItemBehaviorTest {
    UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    redView.backgroundColor = [UIColor redColor];
    
    [self.view addSubview:redView];
    
    self.redView = redView;
    
    UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.frame = CGRectMake(170, CGRectGetHeight(UIScreen.mainScreen.bounds) - 50, 50, 50);
    
    [self.view addSubview:blueView];
    self.blueView = blueView;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 1.根据某一个范围 创建动画者对象
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    // 2.根据某一个动力学元素 创建行为
    // 重力
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
    
    // 碰撞行为
    UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
    
    // 把引用的view设置为边界
    collision.translatesReferenceBoundsIntoBoundary = YES;
    
    // 动力学元素 自身属性
    UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[self.blueView]];
    
    itemBehavior.elasticity = 1; // 弹力
    itemBehavior.density = 0.5; // 密度
    itemBehavior.friction = 0; // 摩擦力
    
    // 3.把行为添加到动画者当中
    [self.animator addBehavior:gravity];
    [self.animator addBehavior:collision];
    [self.animator addBehavior:itemBehavior];
}

#pragma mark - 推(UIPushBehavior)
- (void)pushBehaviorTest {
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.frame = CGRectMake(100, 100, 100, 100);
    
    [self.view addSubview:redView];
    
    self.redView = redView;
}

/*
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 获取触摸对象
    UITouch *t = touches.anyObject;
    
    // 获取手指的位置
    CGPoint p = [t locationInView:t.view];
    
    // 1.创建动画者
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    //    UIPushBehaviorModeContinuous, // 持续的推力(越来越快)
    //    UIPushBehaviorModeInstantaneous // 瞬时的推力(越来越慢)
    
    // 2.创建行为
    UIPushBehavior *push = [[UIPushBehavior alloc] initWithItems:@[self.redView] mode:UIPushBehaviorModeInstantaneous];
    
    // 计算偏移量
    CGFloat offsetX = p.x - self.redView.center.x;
    CGFloat offsetY = p.y - self.redView.center.y;
    
    // 方向
    //        push.angle = M_PI; // 用角度的形式设置方向
    push.pushDirection = CGVectorMake(offsetX, offsetY);
    
    // 量级 (放在设置向量的后面)
    push.magnitude = 1;
    
    // 3.把行为添加到动画者当中
    [self.animator addBehavior:push];
}
*/

#pragma mark - #pragma mark - 附着(UIAttachmentBehavior)-item 偏移量
- (void)attachmentBehaviorTest2 {
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.frame = CGRectMake(100, 100, 100, 100);
    
    redView.alpha = 0.5;
    
    [self.view addSubview:redView];
    
    self.redView = redView;
}

/*
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 获取触摸对象
    UITouch *t = touches.anyObject;
    
    // 获取手指的位置
    CGPoint p = [t locationInView:t.view];
    
    // 1.创建动画者对象
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    // 2.创建行为
    self.attach = [[UIAttachmentBehavior alloc] initWithItem:self.redView offsetFromCenter:UIOffsetMake(20, 80) attachedToAnchor:p];
    
    // 固定长度
    self.attach.length = 100;
    
    // 3.把行为添加到动画者对象当中
    [self.animator addBehavior:self.attach];
    
    // 重力行为
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
    
    // 添加重力行为
    [self.animator addBehavior:gravity];
    
    UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
    collision.translatesReferenceBoundsIntoBoundary = YES;
    [self.animator addBehavior:collision];
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 获取触摸对象
    UITouch *t = touches.anyObject;
    
    // 获取手指的位置
    CGPoint p = [t locationInView:t.view];
    
    self.attach.anchorPoint = p;
    
    __weak typeof(self) weakSelf = self;
    self.attach.action = ^{
        ZJView *bgView = (ZJView *)weakSelf.view;
        
        bgView.stat = weakSelf.redView.center;
        bgView.end = p;
        
        [weakSelf.view setNeedsDisplay];
    };
}
*/

#pragma mark - 附着(UIAttachmentBehavior)-item 和 item 之间
- (void)attachmentBehaviorTest {
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.frame = CGRectMake(100, 100, 100, 100);
    
    redView.alpha = 0.5;
    
    [self.view addSubview:redView];
    self.redView = redView;
    
    UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.frame = CGRectMake(250, 100, 100, 100);
    
    blueView.alpha = 0.5;
    
    [self.view addSubview:blueView];
    
    self.blueView = blueView;
}

/*
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 1.创建动画者对象
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    // 2.创建行为
    self.attach = [[UIAttachmentBehavior alloc] initWithItem:self.redView attachedToItem:self.blueView];
    
    // 3.把行为添加到动画者对象当中
    [self.animator addBehavior:self.attach];
    
    // 重力行为
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
    
    // 添加重力行为
    [self.animator addBehavior:gravity];
}
*/
#pragma mark - 附着(UIAttachmentBehavior)-item 和点之间
- (void)attachmentBehavior {
    UIView *redView = [[UIView alloc] init];
    redView.backgroundColor = [UIColor redColor];
    redView.frame = CGRectMake(100, 100, 100, 100);
    
    redView.alpha = 0.5;
    
    [self.view addSubview:redView];
    
    self.redView = redView;
}

/*
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 获取触摸对象
    UITouch *t = touches.anyObject;
    
    // 获取手指的位置
    CGPoint p = [t locationInView:t.view];
    
    // 1.创建动画者对象
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    // 2.创建行为
    self.attach = [[UIAttachmentBehavior alloc] initWithItem:self.redView attachedToAnchor:p];
    
    // 固定长度
//    self.attach.length = 100;
    
    self.attach.damping = 0.5; // 减幅
    self.attach.frequency = 0.5; // 频率
    
    // 3.把行为添加到动画者对象当中
    [self.animator addBehavior:self.attach];
    
    // 重力行为
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
    
    // 添加重力行为
    [self.animator addBehavior:gravity];
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 获取触摸对象
    UITouch *t = touches.anyObject;
    
    // 获取手指的位置
    CGPoint p = [t locationInView:t.view];
    
    self.attach.anchorPoint = p;
    
    __weak typeof(self) weakSelf = self;
    self.attach.action = ^{
        ZJView *bgView = (ZJView *)weakSelf.view;
        
        bgView.stat = weakSelf.redView.center;
        bgView.end = p;
        
        [weakSelf.view setNeedsDisplay];
    };
}
*/
#pragma mark - 甩(UISnapBehavior)
- (void)snapBehavior {
    UIView *redView = [[UIView alloc] init];
    
    redView.backgroundColor = [UIColor redColor];
    redView.frame = CGRectMake(100, 100, 100, 100);
    
    [self.view addSubview:redView];
    
    self.redView = redView;
}

/*
// 点击屏幕调用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 获取触摸对象
    UITouch *t = touches.anyObject;
    
    // 获取手指的位置
    CGPoint p = [t locationInView:t.view];
    
    // 1.动画者对象
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    // 2.创建行为
    UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:self.redView snapToPoint:p];
    
    snap.damping = 1; // 减速程度
    
    // 3.把行为添加到动画者当中
    [self.animator addBehavior:snap];
}
 */

- (void)collisionBehavior {
    UIView *redView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    redView.backgroundColor = [UIColor redColor];
    
    [self.view addSubview:redView];
    
    self.redView = redView;
    
    UIView *blueView = [[UIView alloc] init];
    blueView.backgroundColor = [UIColor blueColor];
    blueView.frame = CGRectMake(170, CGRectGetHeight(UIScreen.mainScreen.bounds) - 150, 50, 50);
    
    [self.view addSubview:blueView];
    self.blueView = blueView;
}

/*
// 点击屏幕调用
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//    [self gravityBehaviorTest];
//    [self collisionBehaviorTest];
//    [self collisionBehaviorTest2];
//    [self collisionBehaviorTest3];
//    [self collsionBehaviorTest4];
//    [self collsionBehaviorTest5];
}
 */

#pragma mark - 碰撞的代理方法
- (void)collsionBehaviorTest5 {
    // 1.根据某一个范围 创建动画者对象
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    // 2.根据某一个动力学元素 创建行为
    // 重力
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
    
    // 碰撞行为
    UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
    
    // 把引用 view 的 bounds变成边界
    collision.translatesReferenceBoundsIntoBoundary = YES;
    
    // 以一条线为边界
    [collision addBoundaryWithIdentifier:@"key" fromPoint:CGPointMake(0, 200) toPoint:CGPointMake(150, 250)];
    
    // 以一个自定义路径为边界
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.blueView.frame];
    [collision addBoundaryWithIdentifier:@"key1" forPath:path];
    
    // action 实时监听 系统会在 view 动得时候执行这个 block
    collision.action = ^{
        NSLog(@"%@", NSStringFromCGRect(self.redView.frame));
        
        ZJView *bgView = (ZJView *)self.view;
        bgView.redRect = self.redView.frame;
        
        [self.view setNeedsDisplay];
    };
    
    // 设置代理
    collision.collisionDelegate = self;
    
    // 3.把行为添加到动画者当中
    [self.animator addBehavior:gravity];
    [self.animator addBehavior:collision];
}

// 碰撞的代理方法
- (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id<UIDynamicItem>)item withBoundaryIdentifier:(id<NSCopying>)identifier atPoint:(CGPoint)p {
    
    // 需要强转进行判断
    NSString *str = (NSString *)identifier;
    
    if ([str isEqualToString:@"key"]) {
        self.redView.backgroundColor = [UIColor yellowColor];
    } else {
        self.redView.backgroundColor = [UIColor redColor];
    }
}

#pragma mark - 碰撞之action
- (void)collsionBehaviorTest4 {
    // 1.根据某一个范围 创建动画者对象
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    // 2.根据某一个动力学元素 创建行为
    // 重力
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
    
    // 碰撞行为
    UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
    
    // 把引用 view 的 bounds变成边界
    collision.translatesReferenceBoundsIntoBoundary = YES;
    
    // 以一个自定义路径为边界
    UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.blueView.frame];
    [collision addBoundaryWithIdentifier:@"key" forPath:path];
    
    // action 实时监听 系统会在 view 动得时候执行这个 block
    collision.action = ^{
        NSLog(@"%@", NSStringFromCGRect(self.redView.frame));

        ZJView *bgView = (ZJView *)self.view;
        bgView.redRect = self.redView.frame;
        
        [self.view setNeedsDisplay];
        
        // 如果 宽 大于 105 变色
        if (CGRectGetWidth(self.redView.frame) > 105) {
            self.redView.backgroundColor = [UIColor yellowColor];
        } else {
            self.redView.backgroundColor = [UIColor redColor];
        }
    };
    
    // 3.把行为添加到动画者当中
    [self.animator addBehavior:gravity];
    [self.animator addBehavior:collision];
}

#pragma mark - 创建边界
- (void)collisionBehaviorTest3 {
    // 1.根据某一个范围 创建动画者对象
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    // 2.根据某一个动力学元素 创建行为
    // 重力
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
    
    // 碰撞行为
    UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
    
    // 把引用 view 的 bounds变成边界
    collision.translatesReferenceBoundsIntoBoundary = YES;
    
    // 添加边界
    
    // 以一条线为边界
    [collision addBoundaryWithIdentifier:@"key" fromPoint:CGPointMake(0, 200) toPoint:CGPointMake(200, 250)];
    
    // 以一个自定义路径为边界
//    UIBezierPath *path = [UIBezierPath bezierPathWithRect:self.blueView.frame];
//    [collision addBoundaryWithIdentifier:@"key" forPath:path];
    
    // 3.把行为添加到动画者当中
    [self.animator addBehavior:gravity];
    [self.animator addBehavior:collision];
}

#pragma mark - 碰撞行为(UICollisionBehavior)-与另一个item发生碰撞
- (void)collisionBehaviorTest2 {
    // 1.根据某一个范围 创建动画者对象
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    // 2.根据某一个动力学元素 创建行为
    // 重力
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
    
     // 碰撞行为
    UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView, self.blueView]];
    
    // 把引用 view 的 bounds变成边界
    collision.translatesReferenceBoundsIntoBoundary = YES;
    
//    UICollisionBehaviorModeItems        // 仅仅 item 和 item 之间发生碰撞
//    UICollisionBehaviorModeBoundaries   // 仅仅是和边界发生碰撞
//    UICollisionBehaviorModeEverything   // item 和边界都发生碰撞
    
    // 碰撞模式
    collision.collisionMode = UICollisionBehaviorModeEverything;
    
    // 3.把行为添加到动画者当中
    [self.animator addBehavior:gravity];
    [self.animator addBehavior:collision];
}

#pragma mark - 碰撞(UICollisionBehavior)-与应用view碰撞
- (void)collisionBehaviorTest {
    // 1.根据某一个范围（引用View） 创建动画者对象
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    // 2.根据某一个动力学元素 创建行为
    // 重力
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
    
    // 碰撞行为
    UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.redView]];
    
    // 把引用 view 的 bounds变成边界
    collision.translatesReferenceBoundsIntoBoundary = YES;
    
    // 3.把行为添加到动画者当中
    [self.animator addBehavior:gravity];
    [self.animator addBehavior:collision];
}

#pragma mark - 重力(UIGravityBehavior)
- (void)gravityBehaviorTest {
    // 1.根据某一个范围 创建动画者对象
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    
    // 2.根据某一个动力学元素 创建行为
    // 重力
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.redView]];
    
    // 方向
//    gravity.gravityDirection = CGVectorMake(1, 1); // 用向量的形式设置方向
//    gravity.angle = M_PI; // 用角度的形式设置方向
    
    // 量级
    gravity.magnitude = 100;
    
    // 3.把行为添加到动画者当中
    [self.animator addBehavior:gravity];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end
